// OPMLProcessor.cpp: implementation of the OPMLProcessor class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TinyPP.h"
#include "OPMLProcessor.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

OPMLProcessor::OPMLProcessor()
{

}

OPMLProcessor::~OPMLProcessor()
{

}
// Recursive helper that calls a method, that param fp points to, for a hParent node
// and all of its children, its children's children, etc.
// This is one of few cases where I used ->* notation for method call through a pointer
void OPMLProcessor::DoForItemAndChildren( TiXmlNode* parent, FOREACHITEM fp, unsigned int flags /*= 0*/)
{
	// DOPARENTFIRST flag tells us if we want fp to be called on parent node first, then children, or viceversa
	if ( flags & DOPARENTFIRST)
	{
		if ( !( flags & SKIPTOPPARENT))
			(this->*fp)( parent );
	}

	for( TiXmlNode* child = parent->FirstChild(); child; child = child->NextSibling() ){
		DoForItemAndChildren( child, fp, ( flags & DOPARENTFIRST) ? DOPARENTFIRST : 0);
	}

	if ( !(flags & DOPARENTFIRST))
	{
		if ( !( flags & SKIPTOPPARENT))
			(this->*fp)( parent);
	}
}

bool OPMLProcessor::Parse()
{
	TiXmlNode* declarationNode=m_Xmldoc.FirstChild();
	if(declarationNode){
		TiXmlDeclaration* declaration = declarationNode->ToDeclaration();
		if(declaration){
			const char* strTemp=declaration->Encoding();
			if(strTemp){
				m_strEncoding=strTemp;
			}
		}		
	}

	TiXmlElement* root=m_Xmldoc.RootElement();
	if(!root)
		return false;
	TiXmlNode* body=root->FirstChild("body");
	if(!body)
		return false;
	m_pXmlBodyNode = body;
	//DoForItemAndChildren(body,ShowNodeTitle,SKIPTOPPARENT|DOPARENTFIRST);
	return true;
}

bool OPMLProcessor::ParseFile(const char *filename)
{
	Reset();
	if( !m_Xmldoc.LoadFile(filename) ){
		MessageBox(NULL,m_Xmldoc.ErrorDesc(),"failed in parsing opml file",MB_OK);
		return false;
	}
	return Parse();
}

void OPMLProcessor::Reset()
{
	m_strEncoding = "utf-8";
	m_pXmlBodyNode = NULL;
	m_Xmldoc.Clear();
	m_Xmldoc.ClearError();
}

void OPMLProcessor::ShowNodeTitle(TiXmlNode* node)
{
	if(!node)
		return;
	TiXmlElement* element = node->ToElement();
	if(!element)
		return;
	const char* strTitle = element->Attribute("title");
	if(strTitle){
		MessageBox(NULL,strTitle,"OPMLProcessor verify",MB_OK);
	}
}


// build the feed navigation tree by opml
void OPMLProcessor::SynFeedTree(CFeedTree *feedtree)
{
	std::queue<HTREEITEM> queue_tree_nodes;
	std::queue<TiXmlNode* > queue_XmlNodes;

	queue_XmlNodes.push(m_pXmlBodyNode);
	queue_tree_nodes.push(TVI_ROOT);

	while( !queue_tree_nodes.empty() )
	{
		TiXmlNode* parent=queue_XmlNodes.front();
		HTREEITEM treeparent=queue_tree_nodes.front();
		queue_XmlNodes.pop();
		queue_tree_nodes.pop();

		HTREEITEM thisnode = TVI_ROOT;
		const char* strTitle=NULL;
		const char* strTreeNode=parent->ToElement()->Attribute("xmlUrl");

		if(strTreeNode){ // a leaf node			
			strTitle = parent->ToElement()->Attribute("title");
			feedtree->InsertAFeed( GetEncoding()=="utf-8"?UTF8_to_ANSI(strTreeNode).c_str():strTreeNode,
				GetEncoding()=="utf-8"?UTF8_to_ANSI(strTitle).c_str():strTitle,
				treeparent
				);						
		}else{ 
			strTitle = parent->ToElement()->Attribute("title");
			if(strTitle){ // a folder node			
				thisnode = feedtree->InsertAGroup( GetEncoding()=="utf-8"?UTF8_to_ANSI(strTitle).c_str():strTitle,
					"",
					treeparent
					);
			}else{ // the body folder
				thisnode = TVI_ROOT;
			}
		}
		
		for( TiXmlNode* child = parent->FirstChild(); child; child = child->NextSibling() ){
			queue_XmlNodes.push(child);
			queue_tree_nodes.push(thisnode);	
		}						
	}
}
